import * as THREE from "three";
import { TransformControls } from "three/addons/controls/TransformControls.js";
// import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { EditorControls } from "@/utils/EditorControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { ViewHelper } from "three/examples/jsm/helpers/ViewHelper.js";
import { editor } from "@/store";

export let container: HTMLElement;
let canvas: HTMLElement;
export const scene = new THREE.Scene();
export const sceneHelpers = new THREE.Scene();
let camera: any;
let controls: any;
let renderer: any;
let transformControls: any;
let box3Helper = null as any;
let viewHelper = null as any;
let onRenderFcts = [] as any[];
const clock = new THREE.Clock();
const loader = new GLTFLoader();
const raycaster = new THREE.Raycaster();

export function defaultSetting(_container: HTMLElement) {
  try {
    container = _container;
    scene.background = new THREE.Color(0xaaaaaa);
    createCamera();
    createRenderer();
    addViewHelper();
    addGridHelper();
    addBox3Helper();
    addTransformControls();
    createControls();
    window.addEventListener("resize", onWindowResize, false);
    frameRender();
  } catch (error) {
    console.log("defaultSetting", error);
  }
}

function createCamera() {
  camera = new THREE.PerspectiveCamera(50, 1, 0.01, 1000);
  camera.name = "camera";
  camera.aspect = container.offsetWidth / container.offsetHeight;
  camera.position.set(0, 5, 10);
  camera.lookAt(0, 0, 0);
}

function createRenderer() {
  renderer = new THREE.WebGLRenderer({
    antialias: true, // true/false表示是否开启反锯齿
    // alpha: true, // true/false 表示是否可以设置背景色透明
    precision: "highp", // highp/mediump/lowp 表示着色精度选择
    // premultipliedAlpha: false,
    // maxLights: 3,
    // canvas: canvas,
  });
  canvas = renderer.domElement;
  container.appendChild(canvas);

  renderer.autoClear = false; //消除默认背景,解决场景发黑
  renderer.autoUpdateScene = false;
  renderer.setSize(container.offsetWidth, container.offsetHeight);
  // 像素比（和浏览器一致）
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  renderer.shadowMap.enabled = true; //启动阴影
}

function createControls() {
  controls = new EditorControls(camera, canvas);
  // controls = new OrbitControls(camera, renderer.domElement);
  // controls.damping = 0.2;
}

// 渲染方法
export function frameRender() {
  onRenderFcts.forEach((fn: any) => {
    fn();
  });
  //requestAnimationFrame中会自动处理矩阵更新，如果在渲染帧函数中修改对象矩阵，需要手动调取该方法来保持场景中每个对象的世界坐标都是最新的
  sceneHelpers.updateMatrixWorld();
  scene.updateMatrixWorld();
  renderer.render(scene, camera);
  const STEPS_PER_FRAME = 2; //每一帧执行的步骤数
  // 每一帧中进行多次物理更新，需要更高的精度，或者你想要在每一帧中模拟更复杂的交互（如碰撞检测、重力影响等）
  for (let i = 0; i < STEPS_PER_FRAME; i++) {
    // for循环可以提供更平滑的动画效果和更准确的物理模拟
    renderer.render(sceneHelpers, camera);
  }
  viewHelper?.render(renderer);
  requestAnimationFrame(frameRender);
}

// 窗口自适应
function onWindowResize() {
  camera.aspect = container.offsetWidth / container.offsetHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.offsetWidth, container.offsetHeight);
  // render();
}

let timeout = null as any;
export function saveState() {
  clearTimeout(timeout);
  timeout = setTimeout(function () {
    editor.storage.set(editor.toJSON());
  }, 1000);
}

function updateModelInfo() {
  console.log(
    "updateModelInfo",
    transformControls.object,
    transformControls.mode
  );
  switch (transformControls.mode) {
    case "translate":
      break;
    case "scale":
      break;
    case "rotate":
      break;
  }
  // TODO:更新box3Helper
  // viewport.box3Helper.box.setFromCenterAndSize(
  //   viewport.transformControl.object.position.clone(),
  //   viewport.transformControl.object.scale.clone()
  // );
}

// function addAxesHelper() {
//   sceneHelpers.add(new THREE.AxesHelper(5));
// }

function addGridHelper() {
  let gridHelper = new THREE.GridHelper(2000, 100, 0x444444, 0x888888);
  // helper.material.opacity = 0.25;
  // helper.material.transparent = true;
  sceneHelpers.add(gridHelper);
}

function addBox3Helper() {
  const box3 = new THREE.Box3();
  box3Helper = new THREE.Box3Helper(box3, 0xffff00);
  box3Helper.visible = false;
  sceneHelpers.add(box3Helper);
}

function addTransformControls() {
  transformControls = new TransformControls(camera, canvas);
  transformControls.addEventListener("dragging-changed", function (event: any) {
    controls.enabled = !event.value;
  });
  transformControls.addEventListener("objectChange", function () {
    updateModelInfo();
  });
  sceneHelpers.add(transformControls);
}

function addViewHelper() {
  const helperDiv = document.createElement("div");
  helperDiv.style.position = "absolute";
  helperDiv.style.right = "10px";
  helperDiv.style.bottom = "10px";
  helperDiv.style.width = "128px";
  helperDiv.style.height = "128px";
  viewHelper = new ViewHelper(camera, helperDiv);
  container.appendChild(helperDiv);
}

export function setTransformMode(mode: "translate" | "scale" | "rotate") {
  transformControls.setMode = mode;
}

export function onPointerMove(event: any) {
  const pointer = new THREE.Vector2();
  pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
  pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

  raycaster.setFromCamera(pointer, camera);
  const intersects = raycaster.intersectObjects(editor.meshObjects, true); //raycaster无法直接检测到 Group 对象的相交情况，第二参数需设置成true，递归检查所有的后代
  if (intersects.length > 0) {
    const object = intersects[0].object;
    if (object?.parent.type == "Object3D") {
      // 获取loader加载模型的几何对象
      let rootGroup = scene.getObjectByProperty("uuid", object.userData.uuid);
      let rootObj3D = rootGroup?.children?.[0];
      transformControls.attach(rootObj3D);
      box3Helper.box.setFromObject(rootObj3D, true);
      box3Helper.visible = true;
    } else if (object !== transformControls.object) {
      transformControls.attach(object);
    }
  }
}

const handleFilefunc: any = {
  model: createModel,
  video: createVideo,
  audio: createAudio,
  image: createImage,
};
// 添加3d内容
export function add3dObjects(file: any) {
  handleFilefunc[getFileType(file)](file);
}

function animate(model: any) {
  if (!model.animations?.length) return;
  const mixer = new THREE.AnimationMixer(model);
  model.animations.forEach((f: any) => {
    mixer.clipAction(f).setLoop(THREE.LoopRepeat, Infinity).play();
    onRenderFcts.push(() => {
      // 动画和时间同步
      const time = clock.getDelta();
      if (mixer) mixer.update(time);
    });
  });
}

function getFileType(file: any) {
  switch (file.type) {
    case "image/jpeg":
      return "image";
    case "image/png":
      return "image";
    case "video/mp4":
      return "video";
    case "audio/mpeg":
      return "audio";
    default:
      if (file.name.split(".")[1] == "glb") {
        return "model";
      } else {
        return "no";
      }
  }
}

function uploadFile(file: any) {
  return new Promise((resolve) => {
    var reader = new FileReader();
    reader.onload = function () {
      resolve(reader.result);
    };
    reader.readAsArrayBuffer(file);
  });
}

async function createModel(info: any) {
  console.log("createModel", info);
  let data = await uploadFile(info);
  return new Promise((resolve) => {
    loader.parse(data, "", (gltf: any) => {
      gltf.scene.traverse((child: any) => {
        if (child.isMesh) {
          child.castShadow = true;
          child.userData.uuid = gltf.scene.uuid; //为每一个mesh添加一个标识属性
        }
      });
      animate(gltf.scene);
      editor.addObject(gltf.scene);
      editor.modelArr.push(gltf.scene);
      resolve(true);
    });
  });
}

async function createVideo(info: any) {
  console.log("createVideo", info);
  // 初始化video
  const vdoDom = document.createElement("video");
  const videoURL = URL.createObjectURL(info);
  vdoDom.src = videoURL;
  // vdoDom.controls = true;
  vdoDom.autoplay = true;
  vdoDom.crossOrigin = "anonymous"; // 如果视频跨域，需要设置跨域属性
  vdoDom.style.display = "none";
  vdoDom.play();
  // 创建视频贴图
  const texture = new THREE.VideoTexture(vdoDom);
  texture.colorSpace = THREE.SRGBColorSpace; //统一色彩
  const material = new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.DoubleSide,
  });
  return new Promise((resolve) => {
    vdoDom.onloadeddata = () => {
      // 可选：释放 URL 对象，避免内存泄漏
      URL.revokeObjectURL(videoURL);
      const width = vdoDom.videoWidth / 10 || 100;
      const height = vdoDom.videoHeight / 10 || 100;
      const geometry = new THREE.PlaneGeometry(width, height); // 这里假设矩形平面的大小是16x9
      const videoMesh = new THREE.Mesh(geometry, material);
      editor.addObject(videoMesh);
      editor.videoArr.push(videoMesh);
      resolve(true);
    };
  });
}

function createAudio(info: any) {
  console.log("createAudio", info);
  // 初始化音频
  const audioDom = document.createElement("audio");
  const audioURL = URL.createObjectURL(info);
  audioDom.src = audioURL;
  audioDom.autoplay = true;
  audioDom.play();
  // audioDom.controls = false;
  document.body.appendChild(audioDom);
  editor.audioArr.push(audioDom);
  return new Promise((resolve) => {
    resolve(true);
  });
}

function createImage(info: any) {
  console.log("createImage", info);
  const imageURL = URL.createObjectURL(info);
  const image = new Image();
  image.src = imageURL;
  // 初始化纹理
  const textureLoader = new THREE.TextureLoader();
  const texture = textureLoader.load(imageURL);
  texture.colorSpace = THREE.SRGBColorSpace; //统一色彩
  const material = new THREE.MeshPhongMaterial({
    map: texture,
    side: THREE.DoubleSide,
  });
  return new Promise((resolve) => {
    image.onload = function () {
      // 释放 Blob URL
      URL.revokeObjectURL(imageURL);
      // 图片加载完成后获取宽度和高度
      const width = image.width / 100;
      const height = image.height / 100;
      const geometry = new THREE.PlaneGeometry(width, height);
      const imageMesh = new THREE.Mesh(geometry, material);
      editor.addObject(imageMesh);
      editor.imageArr.push(imageMesh);
      resolve(true);
    };
  });
}
